package com.qd.panda.pay;

import com.cdqidi.exception.ApiException;
import com.cdqidi.util.DateUtil;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.qd.panda.service.stroke.order.UserStrokeOrderRefundService;
import com.qd.pay.domain.OrderRefundDTO;
import com.qd.pay.model.Order;
import com.qd.pay.model.OrderTf;
import com.qd.pay.service.OrderTfService;
import com.qd.pay.service.order.OrderService;
import com.qd.pay.service.order.TfOrderService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;


/**
 * 只为测试使用，正式不适用
 * 把没有取到状态报告的订单ID查询出来
 * 然后到天府银行去取状态报告，然后模拟天府银行发送回执信息
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class PayTestService {

    private final OrderService orderService;
    private final OrderTfService orderTfService;
    private final TfOrderService tfOrderService;
    private final UserStrokeOrderRefundService userStrokeOrderRefundService;
    private int i = 0;
    private int i1 = 0;
    private int j = 0;
    private int j1 = 0;
    private static final int NULL_MAX_COUNT = 300;
    private static final int MAX_COUNT = 30;

    @Transactional(rollbackFor = Exception.class)
    public void testOrderState() {
        String sendTime = LocalDate.now() + " 00:00:00";
        List<Order> list = orderService.getNoReportOrder(sendTime);
        if (list.isEmpty()) {
            if (i % NULL_MAX_COUNT == 0) {
                log.info("查询没有取到回执消息的订单，时间: {},数量: {}", sendTime, 0);
                i = 0;
            }
            i++;
        } else {
            if (j % MAX_COUNT == 0) {
                log.info("查询没有取到回执消息的订单，时间: {},数量: {}", sendTime, list.size());
                j = 0;
            }
            j++;
        }
        for (Order order : list) {
            orderState(order);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void testRefundState() {
        String sendTime = LocalDate.now() + " 00:00:00";
        List<OrderRefundDTO> list = userStrokeOrderRefundService.getBaseMapper().getOrderRefund();
        if (list.isEmpty()) {
            if (i1 % NULL_MAX_COUNT == 0) {
                log.info("查询没有取到回执消息的退款单，时间: {},数量: {}", sendTime, 0);
                i1 = 0;
            }
            i1++;
        } else {
            if (j1 % MAX_COUNT == 0) {
                log.info("查询没有取到回执消息的退款单，时间: {},数量: {}", sendTime, list.size());
                j1 = 0;
            }
            j1++;
        }
        for (OrderRefundDTO refundDTO : list) {
            refundState(refundDTO);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void testOrderState(String orderId) {
        Order order = Optional.ofNullable(orderService.getById(orderId)).orElseThrow(() -> new ApiException("订单编号不存在"));
        orderState(order);
    }

    private void orderState(Order order) {
//        log.info("更新回执信息,orderId: {}", order.getOrderId());
        final OrderTf orderTf = Optional.ofNullable(orderTfService.getById(order.getOrderId())).orElseThrow(() -> new ApiException("天府银行订单不存在"));
        JsonNode jsonNode = tfOrderService.orderStateJson(orderTf.getPartner(), orderTf.getSubPartner(), order.getOutTradeNo());
        if (null != jsonNode) {
            ObjectNode objectNode = (ObjectNode) jsonNode;
            String retCode = jsonNode.get("retCode").asText();
            JsonNode timeEndNode = jsonNode.get("time_end");
            if (null == timeEndNode) {
                objectNode.put("time_end", DateUtil.localDateTimeToString(LocalDateTime.now(), "yyyyMMdd HH:mm:ss"));
            }
            objectNode.put("retcode", retCode);
            String tradeState = Optional.ofNullable(jsonNode.get("trade_state")).orElseThrow(() -> new ApiException("支付结果为空")).asText();
            if ("3".equals(tradeState)) {
//                log.info("更新回执信息,当前订单状态为支付中,所以不处理,orderId: {}", order.getOrderId());
                return;
            }
            tfOrderService.payNotify(objectNode);
        }
    }

    private void refundState(OrderRefundDTO orderRefundDTO) {
        log.info("更新退款的回执信息,orderId: {}", orderRefundDTO.getOrderId());
        final OrderTf orderTf = Optional.ofNullable(orderTfService.getById(orderRefundDTO.getOrderId())).orElseThrow(() -> new ApiException("天府银行订单不存在"));
        final Order order = Optional.ofNullable(orderService.getById(orderRefundDTO.getOrderId())).orElseThrow(() -> new ApiException("订单不存在"));
        JsonNode jsonNode = tfOrderService.orderStateJson(orderTf.getPartner(), orderTf.getSubPartner(), order.getOutTradeNo());
        log.info("更新退款的回执信息,返回json: {}", jsonNode);
        if (null != jsonNode) {
            ObjectNode objectNode = (ObjectNode) jsonNode;
            JsonNode refundState = jsonNode.get("refund_state");
            JsonNode timeEndNode = jsonNode.get("time_end");
            if (null == refundState) {
                return;
            }
            if (null == timeEndNode) {
                objectNode.put("refund_time", DateUtil.localDateTimeToString(LocalDateTime.now(), "yyyyMMdd HH:mm:ss"));
            }
            String tradeState = Optional.ofNullable(jsonNode.get("trade_state")).orElseThrow(() -> new ApiException("支付结果为空")).asText();
            if ("3".equals(tradeState)) {
                return;
            }
            String refundStateText = refundState.asText();
            if (refundStateText.equals("1") || refundStateText.equals("2")) {
                //0成功 1失败
                objectNode.put("refund_status", "0");
            } else {
                objectNode.put("refund_status", "1");
            }
            objectNode.put("transaction_id", jsonNode.get("transaction_id").asText());

            objectNode.put("out_refund_no", jsonNode.get("out_refund_no").asText());
            objectNode.put("refund_fee", jsonNode.get("total_fee").decimalValue());
            tfOrderService.refundNotify(objectNode);
        }
    }
}
